home *** CD-ROM | disk | FTP | other *** search
- int
- do_ipcctl(optype, arglast)
- int optype;
- int *arglast;
- {
- register STR **st = stack->ary_array;
- register int sp = arglast[0];
- STR *astr;
- char *a;
- int id, n, cmd, infosize, getinfo, ret;
-
- id = (int)str_gnum(st[++sp]);
- n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
- cmd = (int)str_gnum(st[++sp]);
- astr = st[++sp];
-
- infosize = 0;
- getinfo = (cmd == IPC_STAT);
-
- switch (optype)
- {
- #ifdef HAS_MSG
- case O_MSGCTL:
- if (cmd == IPC_STAT || cmd == IPC_SET)
- infosize = sizeof(struct msqid_ds);
- break;
- #endif
- #ifdef HAS_SHM
- case O_SHMCTL:
- if (cmd == IPC_STAT || cmd == IPC_SET)
- infosize = sizeof(struct shmid_ds);
- break;
- #endif
- #ifdef HAS_SEM
- case O_SEMCTL:
- if (cmd == IPC_STAT || cmd == IPC_SET)
- infosize = sizeof(struct semid_ds);
- else if (cmd == GETALL || cmd == SETALL)
- {
- struct semid_ds semds;
- if (semctl(id, 0, IPC_STAT, &semds) == -1)
- return -1;
- getinfo = (cmd == GETALL);
- infosize = semds.sem_nsems * sizeof(short);
- /* "short" is technically wrong but much more portable
- than guessing about u_?short(_t)? */
- }
- break;
- #endif
- #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
- default:
- fatal("%s not implemented", opname[optype]);
- #endif
- }
-
- if (infosize)
- {
- if (getinfo)
- {
- STR_GROW(astr, infosize+1);
- a = str_get(astr);
- }
- else
- {
- a = str_get(astr);
- if (astr->str_cur != infosize)
- {
- errno = EINVAL;
- return -1;
- }
- }
- }
- else
- {
- int i = (int)str_gnum(astr);
- a = (char *)i; /* ouch */
- }
- errno = 0;
- switch (optype)
- {
- #ifdef HAS_MSG
- case O_MSGCTL:
- ret = msgctl(id, cmd, (struct msqid_ds *)a);
- break;
- #endif
- #ifdef HAS_SEM
- case O_SEMCTL:
- ret = semctl(id, n, cmd, a);
- break;
- #endif
- #ifdef HAS_SHM
- case O_SHMCTL:
- ret = shmctl(id, cmd, (struct shmid_ds *)a);
- break;
- #endif
- }
- if (getinfo && ret >= 0) {
- astr->str_cur = infosize;
- astr->str_ptr[infosize] = '\0';
- }
- return ret;
- }
-
-